home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / Sample Code Update 01⁄96 / MenuScripter 3.1 / Sources / MSFile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-20  |  14.3 KB  |  621 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSFile.c
  3.     
  4.     Version 3.1
  5.     
  6.     Copyright © 1995 Apple Computer, Inc., all rights reserved.
  7.     
  8.     MenuScripter by Nigel Humphreys and Jon Lansdell
  9.     AppleEvent to script extensions by Greg Sutton
  10. */
  11.     
  12. #include <Errors.h>
  13. #include <Resources.h>
  14. #include <Desk.h>
  15. #include <PLStringFuncs.h>
  16. #include <AppleEvents.h>
  17. #include <AERegistry.h>
  18. #include "MSFile.h"
  19.  
  20. /**-----------------------------------------------------------------------
  21.         Name:             FileError
  22.         Purpose:        Puts up an error alert.
  23.     -----------------------------------------------------------------------**/
  24.  
  25.     
  26. #pragma segment File
  27.  
  28. pascal void FileError(Str255 s, Str255 f)
  29.   {
  30.     short    alertResult;
  31.  
  32.     SetCursor(&qd.arrow);
  33.         ParamText(s, f, (unsigned char *)"", (unsigned char *)"");
  34.     alertResult = Alert(ErrorAlert, nil);
  35.     }
  36.  
  37. /**-----------------------------------------------------------------------
  38.         Name:             DoClose
  39.         Purpose:        Closes a window.
  40.     -----------------------------------------------------------------------**/
  41.  
  42. #pragma segment File
  43.  
  44. pascal OSErr DoClose(WindowPtr aWindow,Boolean canInteract,DescType dialogAnswer)
  45.   {
  46.     DPtr    aDocument;
  47.     short   alertResult;
  48.     Str255  theName;
  49.         OSErr   myErr;
  50.                         
  51.         myErr = noErr;
  52.         
  53.     if (gWCount>0)
  54.       {
  55.         aDocument = DPtrFromWindowPtr(aWindow);
  56.             
  57.                 if (aDocument->dirty)
  58.                     if (canInteract && (dialogAnswer==kAEAsk))
  59.                         {
  60.                             if (aDocument->everSaved == false)
  61.                                 GetWTitle(aWindow, theName); /* Pick it up as a script may have changed it */
  62.                             else
  63.                                 PLstrcpy(theName, aDocument->theFileName);
  64.                                 
  65.                             ParamText((unsigned char *)"\pSave Changes for ", theName, (unsigned char *)"", (unsigned char *)"");
  66.                           SetCursor(&qd.arrow);
  67.                             alertResult = Alert(AdviseAlert, nil);
  68.                             switch (alertResult) {
  69.                               case aaSave    :if (aDocument->everSaved == false)
  70.                                                                     {
  71.                                                                         myErr = GetFileNameToSaveAs(aDocument);
  72.                                                                         if (myErr == noErr)
  73.                                                                             myErr = DoSave(aDocument, aDocument->theFSSpec);
  74.                                                                     }
  75.                                                                 else
  76.                                                                     myErr = SaveUsingTemp(aDocument);
  77.                                                                 break;
  78.                                                                 
  79.                                 case aaCancel : return(userCanceledErr);
  80.                                                 break;
  81.                                                                 
  82.                                 case aaDiscard: aDocument->dirty = false;
  83.                             }
  84.                         }
  85.                     else
  86.                         {
  87.                             if (dialogAnswer==kAEYes)
  88.                                 if (aDocument->everSaved == false)
  89.                                     {
  90.                                         if (canInteract)
  91.                                             {
  92.                                               myErr = GetFileNameToSaveAs(aDocument);
  93.                                                 if (myErr==noErr)
  94.                                                     myErr = DoSave(aDocument, aDocument->theFSSpec);
  95.                                             }
  96.                                         else    
  97.                                             return(errAENoUserInteraction);
  98.                                     }
  99.                                 else
  100.                                     myErr = SaveUsingTemp(aDocument);
  101.                             else
  102.                                 myErr = noErr; /* Don't save */
  103.                         }
  104.                 
  105.                 if (myErr==noErr)
  106.                     {
  107.                         CloseMyWindow(aWindow);
  108.                     }
  109.             }
  110.         else
  111.           myErr = errAEIllegalIndex;
  112.             
  113.         return(myErr);
  114.     }
  115.  
  116. #pragma segment File
  117.  
  118. //  DoQuit
  119. //  saveOpt - one of kAEAsk,kAEYes,kAENo
  120. //  if kAEYes or kAEAsk then AEInteactWithUser should have been called
  121. //  before DoQuit. Assumes that it can interact if it needs to.
  122.  
  123. pascal void DoQuit(DescType saveOpt)
  124.   {
  125.     WindowPtr    aWindow;
  126.     WindowPtr    nextWindow;
  127.     WindowPeek   nextWPeek;
  128.     short        theKind;
  129.     OSErr        check;
  130.  
  131.     aWindow = FrontWindow();
  132.      
  133.         while (aWindow)
  134.             {
  135.                 nextWPeek  = ((WindowPeek)aWindow)->nextWindow;
  136.                 nextWindow = &nextWPeek->port;
  137.                 if (Ours(aWindow))
  138.                     {
  139.                         check = DoClose(aWindow, true, saveOpt);
  140.                         if (check!=noErr)
  141.                             return;
  142.                     }
  143.                 else
  144.                     {
  145.                         theKind = ((WindowPeek)aWindow)->windowKind;
  146.                         if (theKind < 0)
  147.                             CloseDeskAcc(theKind);
  148.                     }
  149.                 aWindow = nextWindow;
  150.             }     /*WHILE loop*/
  151.         gQuitting = true;
  152.     }
  153.  
  154. pascal OSErr GetFile(FSSpec *theFSSpec)
  155.   {
  156.     SFTypeList         myTypes;
  157.     StandardFileReply  reply;
  158.  
  159.         myTypes[0] = 'TEXT';
  160.  
  161.         StandardGetFile(nil, 1, myTypes, &reply);
  162.  
  163.         if (reply.sfGood)
  164.             {
  165.                 *theFSSpec = reply.sfFile;
  166.                 return(noErr);
  167.             }
  168.         else
  169.             return(userCanceledErr);
  170.  }
  171.  
  172. #pragma segment File
  173.  
  174.  
  175. pascal OSErr DoCreate(FSSpec theSpec)
  176.   {
  177.       OSErr err;
  178.  
  179.       err = FSpCreate(&theSpec, MenuScripterAppSig, 'TEXT', smSystemScript);
  180.  
  181.       if (err != noErr)
  182.               ShowError((unsigned char *)"\pDoCreate", err);
  183.                 
  184.             return(err);
  185.     }
  186.  
  187. #pragma segment File
  188.  
  189.  
  190. pascal OSErr WriteFile(DPtr      theDocument,
  191.                                              short     refNum,
  192.                        FSSpec    theFSSpec)
  193.   {
  194.     short        resFile;
  195.     long         length;
  196.     HHandle      theHHandle;
  197.     StScrpHandle theSHandle;
  198.     OSErr        err;
  199.     StringHandle theAppName;
  200.         short        oldSelStart;
  201.         short        oldSelEnd;
  202.         Handle       thePHandle;
  203.         Handle       myText;
  204.                 
  205. /*        WriteFile := 1; */
  206.  
  207.     /*first write out the text to the data fork*/
  208.         
  209.         length = (*(theDocument->theText))->teLength;
  210.         
  211.         myText = (*(theDocument->theText))->hText;
  212.         
  213.     HLock(myText);
  214.     
  215.         err = FSWrite(refNum, &length, *myText);
  216.         if (err)
  217.           return(err);
  218.             
  219.     HUnlock(myText);
  220.  
  221.         /*we are writing to a temporary file, so we need to create the resource file*/
  222.         /*before writing out the resources*/
  223.         /*now open the resource file*/
  224.         
  225.         HCreateResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  226.         err = ResError();
  227.         if (err)
  228.           {
  229.                 ShowError((unsigned char *)"\pHCreateResFile", err);
  230.                 return(err);
  231.             }
  232.  
  233.     resFile = HOpenResFile(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name, fsWrPerm);
  234.     err = ResError();
  235.  
  236.     if (err)
  237.           {
  238.                 ShowError((unsigned char *)"\pHOpenResFile", err);
  239.                 return(err);
  240.             }
  241.  
  242.      /*write out our 'TFSF' resource to file*/
  243.                 
  244.         oldSelStart = (*(theDocument->theText))->selStart;
  245.         oldSelEnd   = (*(theDocument->theText))->selEnd;
  246.         TESetSelect(0,32000, theDocument->theText);
  247.                 
  248.     theSHandle = GetStylScrap(theDocument->theText);
  249.                 
  250.         TESetSelect(oldSelStart,oldSelEnd, theDocument->theText);
  251.                 
  252.     AddResource((Handle)theSHandle, 'TFSF', 255, (unsigned char *)"\pStyle Info");
  253.     err = ResError();
  254.     if (err)
  255.           {
  256.                 ShowError((unsigned char *)"\pAddResource- TFSF", err);
  257.                 return(err);
  258.             }
  259.                     
  260.         /* write out the printer info */
  261.                 
  262.         if (theDocument->thePrintSetup)
  263.             {
  264.                 thePHandle = (Handle)theDocument->thePrintSetup;
  265.                 err = HandToHand(&thePHandle);
  266.                 
  267.                 AddResource(thePHandle, 'TFSP', 255, (unsigned char *)"\pPrinter Info");
  268.                 err = ResError();
  269.                 if (err)
  270.                     {
  271.                         ShowError((unsigned char *)"\pAddResource- TFSP", err);
  272.                         return(err);
  273.                     }
  274.             }
  275.                 
  276.                 
  277.         theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  278.     HLock((Handle)theHHandle);
  279.  
  280.         GetFontName(theDocument->theFont, (unsigned char *)&(*theHHandle)->theFont);
  281.         (*theHHandle)->theSize     = theDocument->theSize;
  282.         (*theHHandle)->theStyle    = theDocument->theStyle;
  283.         (*theHHandle)->lastID      = theDocument->lastID;
  284.  
  285.         HUnlock((Handle)theHHandle);
  286.  
  287.         AddResource((Handle)theHHandle, 'TFSS', 255, (unsigned char *)"\pHeader Info");
  288.  
  289.         err = ResError();
  290.         if (err)
  291.             {
  292.                 ShowError((unsigned char *)"\pAddResource- TFSS", err);
  293.                 return(err);
  294.             }
  295.  
  296.         /*Now put an AppName in for Finder in 7.0*/
  297.  
  298.         theAppName = (StringHandle)NewHandle(20); // at least as long as (unsigned char *)"\pMenuScripter"
  299.         PLstrcpy(*theAppName,(unsigned char *)"\pMenuScripter");
  300.         
  301.         AddResource((Handle)theAppName, 'STR ', -16396, (unsigned char *)"\pFinder App Info");
  302.  
  303.         err = ResError();
  304.  
  305.         if (err)
  306.             {
  307.                 ShowError((unsigned char *)"\pAppName", err);
  308.                 return(err);
  309.             }
  310.  
  311.         CloseResFile(resFile);
  312.  
  313.         return(noErr);
  314.     } /* WriteFile */
  315.  
  316. #pragma segment File
  317.  
  318. pascal OSErr ReadFile(DPtr   theDocument,
  319.                                             short  refNum,
  320.                       Str255 fn)
  321.  {
  322.         long            theSize;
  323.         short           resFile;
  324.         OSErr           err;
  325.         HHandle         aHandle;
  326.         Handle          gHandle;
  327.  
  328.         err = GetEOF(refNum, &theSize);
  329.                 if (err)
  330.           return(err);
  331.  
  332.         /*we're only using TE, so check that there is not more than 32K worth of text*/
  333.                 
  334.         if (theSize > 32000)
  335.           return(1);
  336.  
  337.         gHandle = NewHandle(theSize);
  338.         HLock(gHandle);
  339.                 err = FSRead(refNum, &theSize, *gHandle);
  340.                 
  341.         if (err)
  342.           {
  343.             HUnlock(gHandle);
  344.                         return(err);
  345.           }
  346.                                 
  347.                 resFile = HOpenResFile(theDocument->theFSSpec.vRefNum, 
  348.                                                              theDocument->theFSSpec.parID,
  349.                                                              fn,
  350.                                                              fsWrPerm);
  351.                 if (resFile == -1)
  352.                     err = fnfErr;
  353.                 
  354.                 if (err==noErr)
  355.                     {
  356.                         aHandle = nil;
  357.         
  358.                         if (Count1Resources('TFSS'))
  359.                             aHandle = (HHandle)Get1Resource('TFSS', 255);
  360.                             
  361.                         /*
  362.                             New Format Info
  363.                         */
  364.                         
  365.                         aHandle = nil;
  366.                         
  367.                         if (Count1Resources('TFSF'))
  368.                             aHandle = (HHandle)Get1Resource('TFSF', 255);
  369.                             
  370.                         HLock(gHandle);
  371.                         TEStylInsert(    *gHandle,
  372.                                                     GetHandleSize(gHandle),
  373.                                                     (StScrpHandle)aHandle,
  374.                                                     theDocument->theText);
  375.                                         
  376.                         HUnlock(gHandle);
  377.                         
  378.                         /*
  379.                             If there is a print record saved, ditch the old one
  380.                             created by new document and fill this one in
  381.                         */
  382.                         if (Count1Resources('TFSP'))
  383.                             {
  384.                                 if (theDocument->thePrintSetup)
  385.                                     DisposHandle((Handle)theDocument->thePrintSetup);
  386.                                 
  387.                                 theDocument->thePrintSetup = (THPrint)Get1Resource('TFSP', 255);
  388.                               err = HandToHand((Handle *)&theDocument->thePrintSetup);
  389.                                 
  390.                                 PrValidate(theDocument->thePrintSetup);
  391.                             }
  392.  
  393.                         CloseResFile(resFile);
  394.         
  395.                         err = ResError();
  396.                         if (err)
  397.                             {
  398.                                 ShowError((unsigned char *)"\pread file- CloseResFile", err);
  399.                                 return(err);
  400.                             }
  401.           }
  402.                 else
  403.                     TESetText(*gHandle, 
  404.                               GetHandleSize(gHandle), 
  405.                                         theDocument->theText);
  406.                     
  407.                 if (gHandle)
  408.                     DisposHandle(gHandle);
  409.                     
  410.                 if (err==fnfErr)
  411.                     err = noErr;
  412.  
  413.         return(err);
  414.         } /* ReadFile */
  415.  
  416. /** -----------------------------------------------------------------------
  417.         Name:             GetFileContents
  418.         Purpose:        Opens the document specified by theFSSpec and puts
  419.                                 the contents into theDocument.
  420.      -----------------------------------------------------------------------**/
  421.  
  422.     
  423. #pragma segment File
  424.  
  425. pascal OSErr GetFileContents(FSSpec theFSSpec, DPtr theDocument)
  426.   {
  427.      OSErr            err;
  428.      short            theRefNum;
  429.  
  430.             /*this can be called from two places- on an OpenDoc AppleEvent*/
  431.             /*and by the user just selecting Open from the File Menu*/
  432.             /*assume that the CFS is correct when the routine is called*/
  433.  
  434.             err = FSpOpenDF(&theFSSpec,
  435.                                           fsRdWrPerm,
  436.                                           &theRefNum);
  437.             if (err)
  438.                 {
  439.                     ShowError((unsigned char *)"\pFSpOpenDF", err);
  440.                     return(err);
  441.                 }
  442.             else
  443.                 {
  444.                     err = ReadFile(theDocument, theRefNum, theFSSpec.name);
  445.                     if (err)
  446.                         {
  447.                             ShowError((unsigned char *)"\pReadFile", err);
  448.                             return(err);
  449.                         }
  450.                     err=FSClose(theRefNum);
  451.                     if (err)
  452.                         {
  453.                             ShowError((unsigned char *)"\pFSClose", err);
  454.                             return(err);
  455.                         }
  456.                     return(noErr);
  457.                 }
  458.         }
  459.  
  460.     
  461. #pragma segment File
  462.  
  463. pascal OSErr SaveUsingTemp(DPtr theDocument)
  464.   {
  465.     Str255           tempName;
  466.     OSErr            err;
  467.         FSSpec                tempFSSpec;
  468.  
  469.         /*save the file to disk using a temporary file*/
  470.         /*this is the recommended way of doing things*/
  471.         /*first write out the file to disk using a temporary filename*/
  472.         /*if it is sucessfully written, exchange the temporary file with the last one saved*/
  473.     /*then delete the temporary file- so if anything goes wrong, the original version is still there*/
  474.         /*first generate the temporary filename*/
  475.  
  476.         GetTempFileName(theDocument, (unsigned char *)&tempName);
  477.         /*create this file on disk*/
  478.  
  479.         tempFSSpec      = theDocument->theFSSpec;
  480.         PLstrcpy(tempFSSpec.name,tempName);
  481.             
  482.         err = DoCreate(tempFSSpec);    
  483.  
  484.         /*now save the file as normal*/
  485.         
  486.         if (err==noErr)
  487.             err = DoSave(theDocument, tempFSSpec);
  488.         
  489.         if (err == noErr)
  490.             err = FSpExchangeFiles(&tempFSSpec, &theDocument->theFSSpec);
  491.  
  492.         /*we've exchanged the files, now delete the temporary one*/
  493.         
  494.         if (err==noErr)
  495.           err = FSpDelete(&tempFSSpec);
  496.  
  497.         return(err);
  498.     }
  499.  
  500.     
  501. #pragma segment File
  502.  
  503. /*
  504.     Fills in the document record with the user chosen destination
  505. */
  506.  
  507. pascal OSErr GetFileNameToSaveAs(DPtr theDocument)
  508.     {            
  509.     StandardFileReply   reply;
  510.     OSErr               err;
  511.         Str255              suggestName;
  512.  
  513.         GetWTitle(theDocument->theWindow, suggestName);
  514.  
  515.         StandardPutFile((unsigned char *)"\pSave Document As:", suggestName, &reply);
  516.  
  517.     if (reply.sfGood)
  518.             {                
  519.                 err = FSpDelete(&reply.sfFile);
  520.                 
  521.                 if (!((err==noErr) || (err==fnfErr)))
  522.                     return(err);
  523.                 else
  524.                     err = noErr;
  525.                     
  526.                 theDocument->theFSSpec = reply.sfFile;
  527.                 PLstrcpy(theDocument->theFileName, reply.sfFile.name);
  528.             }
  529.         else
  530.             err = userCanceledErr;
  531.         
  532.         return(err);
  533.  } /* GetFileNameToSaveAs */
  534.  
  535.     
  536. #pragma segment File
  537.  
  538. pascal OSErr DoSave(DPtr   theDocument, FSSpec theFSSpec)
  539.   {
  540.     short      refNum;
  541.     OSErr      fileErr;
  542.  
  543.         fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  544.         
  545.         if (fileErr == fnfErr)
  546.             {
  547.               fileErr = DoCreate(theFSSpec);
  548.                 
  549.                 if (fileErr)
  550.                     return(fileErr);
  551.                     
  552.                 fileErr = FSpOpenDF(&theFSSpec, fsRdWrPerm, &refNum);
  553.             }
  554.  
  555.         if (fileErr == noErr)
  556.             {
  557.               fileErr = WriteFile(theDocument, refNum, theFSSpec);
  558.                 
  559.                 if (fileErr==noErr)
  560.                     theDocument->dirty = false;
  561.                     
  562.                 fileErr = FSClose(refNum);
  563.             }
  564.         else
  565.             FileError((unsigned char *)"\perror opening file ", theFSSpec.name);
  566.         
  567.         return(fileErr);
  568.     }
  569.  
  570.     
  571. #pragma segment File
  572.  
  573. pascal OSErr OpenOld(FSSpec aFSSpec)
  574.     {        
  575.       DPtr  theDocument;
  576.         OSErr fileErr;
  577.  
  578.         theDocument = NewDocument(true);
  579.         
  580.         SetWTitle(theDocument->theWindow, aFSSpec.name);
  581.         
  582.         SetPort(theDocument->theWindow);
  583.         
  584.         theDocument->theFSSpec   = aFSSpec;
  585.         
  586.         PLstrcpy(theDocument->theFileName,aFSSpec.name);
  587.         
  588.         theDocument->dirty       = false;
  589.         theDocument->everSaved   = true;
  590.  
  591.     fileErr = GetFileContents(aFSSpec, theDocument);
  592.         
  593.         if (fileErr == noErr)
  594.             {
  595.                 ResizeWindow(theDocument);
  596.                 ShowWindow(theDocument->theWindow);
  597.             }
  598.         else
  599.             FileError((unsigned char *)"\pError Opening ", aFSSpec.name);
  600.                     
  601.         return(fileErr);
  602.     } /* OpenOld */
  603.  
  604.     
  605. #pragma segment File
  606.  
  607. pascal OSErr OpenUsingAlias(AliasHandle theAliasH)
  608.   {
  609.     OSErr    err;
  610.     FSSpec   aFSSpec;
  611.     Boolean  dummy;
  612.  
  613.         err = ResolveAlias(nil, theAliasH, &aFSSpec, &dummy);
  614.         
  615.         if (err == noErr)
  616.             err = OpenOld(aFSSpec);
  617.                     
  618.         return(err);
  619.     }
  620.  
  621.